#include "stdafx.h"
#include <boost/test/auto_unit_test.hpp>
#include "bmock.hpp"
#include "bmock_control_tools_mock.hpp"

static void f(int x, int y) {
	MOCK_VOID(2, (IN(x), IN(x)));
}
static void g(int x, int y) {
	MOCK_VOID(1, (IN(x)));
}

static void h(int x, int y) {
	MOCK_VOID(2, (IN(x), IN(y)));
}

namespace bmock
{
	static const int x = 25;
	static const std::string xStr = boost::lexical_cast<std::string>(x);
	static const int y = 12;
	static const std::string yStr = boost::lexical_cast<std::string>(y);

	BOOST_AUTO_TEST_CASE(test_same_parameter_more_than_once_newmocks) 
	{
		__BMOCK_CONTROL(c);		
		const control_tools_ptr t(new control_tools_mock(c));

		__BMOCK_EXPECT_RETURN_C(c,false,t->warn(message(ARGUMENT_APPEARS_MORE_THAN_ONCE, "x"), location(__FILE__, 7)));
		__BMOCK_EXPECT_RETURN_C(c,false,t->check_equal(xStr,xStr,message(ARG_VALUE,"x"), location(__FILE__,__LINE__+6)));
		__BMOCK_EXPECT_RETURN_C(c,false,t->check_equal(xStr,xStr,message(ARG_VALUE,"x"), location(__FILE__,__LINE__+5)));
		__BMOCK_REPLAY_C(c);
		{
			test_mode_control c1(location(__FILE__,__LINE__),t);
			__BMOCK_CREATE_MOCK_C((&c1), *);
			__BMOCK_EXPECT_C(c1,f(x,y));
			__BMOCK_REPLAY_C(c1);
			BOOST_CHECK_NO_THROW(f(x,y));
			__BMOCK_VERIFY_C(c1);
		}
		__BMOCK_VERIFY_C(c);
	}

	BOOST_AUTO_TEST_CASE(test_different_num_of_parameters_newmocks) 
	{
		__BMOCK_CONTROL(c);		
		const control_tools_ptr t(new control_tools_mock(c));

		__BMOCK_EXPECT_RETURN_C(c,false,t->warn_not_equal(1, 2, message(ARGUMENTS_NUM_NOT_EQUAL), location(__FILE__, 10)));
		__BMOCK_EXPECT_RETURN_C(c,false,t->check_equal(xStr,xStr,message(ARG_VALUE,"x"), location(__FILE__,__LINE__+5)));		
		__BMOCK_REPLAY_C(c);
		{
			test_mode_control c1(location(__FILE__,__LINE__),t);
			__BMOCK_CREATE_MOCK_C((&c1), *);
			__BMOCK_EXPECT_C(c1,g(x,y));
			__BMOCK_REPLAY_C(c1);
			BOOST_CHECK_NO_THROW(g(x,y));
			__BMOCK_VERIFY_C(c1);
		}
		__BMOCK_VERIFY_C(c);
	}

	BOOST_AUTO_TEST_CASE(test_no_warnings_newmocks) 
	{
		__BMOCK_CONTROL(c);
		const control_tools_ptr t(new control_tools_mock(c));

		__BMOCK_EXPECT_RETURN_C(c,false,t->check_equal(xStr,xStr,message(ARG_VALUE,"x"), location(__FILE__,__LINE__+6)));		
		__BMOCK_EXPECT_RETURN_C(c,false,t->check_equal(yStr,yStr,message(ARG_VALUE,"y"), location(__FILE__,__LINE__+5)));		
		__BMOCK_REPLAY_C(c);
		{
			test_mode_control c1(location(__FILE__,__LINE__),t);
			__BMOCK_CREATE_MOCK_C((&c1), *);
			__BMOCK_EXPECT_C(c1,h(x,y));
			__BMOCK_REPLAY_C(c1);
			BOOST_CHECK_NO_THROW(h(x,y));
			__BMOCK_VERIFY_C(c1);
		}
		__BMOCK_VERIFY_C(c);
	}

	struct WarningsThisTester2
	{
		void h(int x, int y) 
		{
			STATIC_MOCK_VOID(3, (IN_PTR(this), IN(x), IN(y)));
		} 
	};

	BOOST_AUTO_TEST_CASE(test_no_warnings_with_this_parameter_newmocks) 
	{
		WarningsThisTester2 wtt;
		std::string wttAddr = BMOCK_HEX_PREFIX+boost::lexical_cast<std::string>(&wtt);

		__BMOCK_CONTROL(c);
		const control_tools_ptr t(new control_tools_mock(c));

		__BMOCK_EXPECT_RETURN_C(c,false,t->check_equal(wttAddr,wttAddr,message(ARG_VALUE,"this"), location(__FILE__,__LINE__+6)));		
		__BMOCK_EXPECT_RETURN_C(c,false,t->check_equal(xStr,xStr,message(ARG_VALUE,"x"), location(__FILE__,__LINE__+5)));		
		__BMOCK_EXPECT_RETURN_C(c,false,t->check_equal(yStr,yStr,message(ARG_VALUE,"y"), location(__FILE__,__LINE__+4)));		
		__BMOCK_REPLAY_C(c);
		{
			test_mode_control c1(location(__FILE__,__LINE__),t);
			__BMOCK_EXPECT_C(c1,wtt.h(x,y));
			__BMOCK_REPLAY_C(c1);
			BOOST_CHECK_NO_THROW(wtt.h(x,y));
			__BMOCK_VERIFY_C(c1);
		}
		__BMOCK_VERIFY_C(c);
	}
}